//SamXIAO
#include <bits/stdc++.h>
using namespace std;

int ans, n, m, cap;

#define szARR_CNT_OF(x) sizeof(x) / sizeof(x[0])
#define TO_BOOL(x, mask) (x & mask) ? 1 : 0
struct room_t {
   int x, y, v;
   bool w, e, n, s, flag;
   room_t(){};
   room_t(int x, int y, int v) : x(x), y(y), v(v) {
      setWall(v);
   }
   void setWall(int v) {
      v = v;
      w = TO_BOOL(v, 1);
      n = TO_BOOL(v, 2);
      e = TO_BOOL(v, 4);
      s = TO_BOOL(v, 8);
   }
};
room_t a[108][106];

inline bool isIn(int x, int y) {
   return 1 <= x && 1 <= y && x <= n && y <= m;
}

void dfs(int x, int y) {
   if (!isIn(x, y) || a[x][y].flag) return;
   cap++;
   a[x][y].flag = true;
   int nx, ny;
   nx = x, ny = y - 1;  // west
   if (isIn(nx, ny) && !a[x][y].w && !a[nx][ny].e) dfs(nx, ny);
   nx = x, ny = y + 1;  // east
   if (isIn(nx, ny) && !a[x][y].e && !a[nx][ny].w) dfs(nx, ny);
   nx = x + 1, ny = y;  // s
   if (isIn(nx, ny) && !a[x][y].s && !a[nx][ny].n) dfs(nx, ny);
   nx = x - 1, ny = y;  // n
   if (isIn(nx, ny) && !a[x][y].n && !a[nx][ny].s) dfs(nx, ny);
}

void work1() {
   scanf("%d%d", &n, &m);
   for (int i = 1; i <= n; i++)
      for (int j = 1; j <= m; j++) {
         int x;
         scanf("%d", &x);
         a[i][j].setWall(x);
      }

   int maxx = 0;
   for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= m; j++) {
         if (!a[i][j].flag) {
            cap = 0;
            ans++;
            dfs(i, j);
            if (maxx < cap) maxx = cap;
         }
      }
   }

   printf("%d\n%d", ans, maxx);
}

int main() {
   work1();
   return 0;
}
